home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The PC-SIG Library 10
/
The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso
/
PC_SIGCD
/
20
/
5
/
DISK2058.ZIP
/
UNFAST.EXE
/
DC.F
< prev
next >
Wrap
Text File
|
1980-01-01
|
33KB
|
1,884 lines
;Debugger written in FAST.
;Written by Peter Campbell Jan------ 1988.
;Much faster and more versatile than DEBUG.
;Able to debug DOS interupts. Screen shows more of use, including all registers
;and the next 6 instructions in window format.
const MAX_SYMBOLS=5120,UNASM_SCREEN=24,DISK_LEN=1024
var TX,POSITION,FINISH,WAITING,WAITFKEY,CUR_IP,CUR_CS,CUR_DX
var CS,IP,BOXING,DISK_OUTPUT,PRINTER_OUTPUT,IO_OUT,SCROLLF
var GET_SYMBOL,SYMBOLS,ORG_IP,BYTE,DPLACE
COMMAND ? 64
PREVIOUS ? 64
DISK_START ? DISK_LEN
DISK_END = DISK_START+DISK_LEN
BUFFER ? 82
SBUFFER ? 82
#inpend=0
#errors off
HEX=1
DELAY=0
FILTER=0
proc ememory print bios "Insufficient memory!!!":terminate
LAST_TYPED=0
page 0
screen 3
SYS=allocate MAX_SYMBOLS/8+16:if error then ememory
PRG=allocate 4096:if error then ememory ;64k program. temp
dos 35(3)
BRK_SEG=reg es:BRK_OFF=reg bx
dos 35(1)
INT_SEG=reg es:INT_OFF=reg bx
dos 35(10)
SCR_SEG=reg es:SCR_OFF=reg bx
poke SOFF,SCR_OFF:poke SSEG,SCR_SEG
CUR_REG=0
BOXING=1 ;Initially use a drawn box on the screen.
reg dx=SCRCHK:dos 25(10)
proc WRITE5(WL,WS)
{
if (WL+DPLACE)>=DISK_END then
{
write #5,DPLACE-(DISK_START) from DISK_START
DPLACE=DISK_START
}
moveb WL from WS to DPLACE
DPLACE+=WL
}
proc CLOSE5
{
if DPLACE<>DISK_START then
write #5,DPLACE-(DISK_START) from DISK_START:if error then return
close #5
}
proc PRINT_OO(OO) if OO then print "on"; else print "off";
function YESNO(DEF)
{
loctocur
forever
{
wait for keypressed
K=ucase key
if K='Y' then print chr K:return 1
if K='N' then print chr K:return 0
if K=13 then print:return DEF
}
}
function END_OF_LINE
{
M=BUFFER+79
while M>=BUFFER
{
if peekb M<>' ' then goto END_FOUND
M--
}
END_FOUND:
return 1+M
}
function COMP_BUFFER
{
EST=END_OF_LINE
ST=BUFFER:F=SBUFFER
X=0
while ST below EST
{
B=peekb ST
if B=' ' then
{
BL=(X and 248)+8
FLAG=1
for A=1 to BL-X
if peekb (ST+A-1)<>' ' then goto SPPUT
next A
B=9:ST+=A-2:X=BL-1
}
SPPUT:
pokeb F,B:F++
X++:ST++
}
poke F,0a0dh
return F+2-(SBUFFER)
}
proc OUTPUT_LINE
{
if IO_OUT then
{
OW=80:if BOXING then OW=68
if PRINTER_OUTPUT then
{
reg dx=0,ax=2:int 17h:PS=high reg ax
if (PS and 00111001b)<>00010000b then
{
PRINTER_OUTPUT=0
print "Printer not ready!":beep:return
}
OM=4000-160 ; Bottom line.
repeat OW lprint chr video[OM]b;:OM+=2
lprint
}
if DISK_OUTPUT then
{
OM=4000-160 ; Bottom line.
fill 40 from BUFFER with 2020h
DO=BUFFER
repeat OW pokeb DO,video[OM]b:OM+=2:DO++
WRITE5(COMP_BUFFER,SBUFFER)
if error then DISK_OUTPUT=0:CLOSE5:print "Disk file error!":beep
}
}
}
proc PRINT_8088(P8_ADD)
{
LEN8=0
while peekb P8_ADD print chr peek P8_ADD;:P8_ADD++:LEN8++
repeat 7-LEN8 print " ";
}
proc PRINT_8088W(P8_ADD)
{
LEN8=0
while peekb P8_ADD print chr peek P8_ADD;:P8_ADD++:LEN8++
if BYTE and 1 then print "W"; else print "B";
if 6-LEN8 then repeat 6-LEN8 print " ";
}
proc SKIP while peekb POSITION=' ' POSITION++
function END_LINE
{
SKIP
if peekb POSITION=13 then return 1
return 0
}
function DIGIT
{
L=peekb POSITION
if (L=' ') or (L=':') or (L=13) then return 100
POSITION++
LNUM=L-'0'
if LNUM>9 then LNUM-=7
if (LNUM<0) or (LNUM>15) then return 255
return LNUM
}
function HEX_NUMBER(DEFAULT)
{
DIGCNT=0:VALUE=0
while DIGCNT<4
{
X=DIGIT
if X=100 then goto CHECK_NUM
if X=255 then print "Must be hex notation.":ANY_ERRORS=1:return
VALUE=VALUE*16+X:DIGCNT++
}
CHECK_NUM:
if not DIGCNT then return DEFAULT
return VALUE
}
proc UNASM_CLINE
{
X=68-((locpos mod 160)/2)
if X>0 then repeat X print " ";
}
function WAIT_KEY
{
if WAITFKEY then
{
if WAITING then
{
wait for keypressed
KS=keyscan:R=low KS
if R=13 then WAITING=0
if R=27 then return 1
}
if keypressed then
{
KS=keyscan:R=low KS
if R=27 then return 1
if R<>13 then WAITING=1
t2:
}
else
{
if DELAY then repeat DELAY*6000 {}
}
}
return 0
}
proc NEW_SEG(NEWS,NEWO)
{
SKIP
if peekb POSITION=':' then print "Segment?":ANY_ERRORS=1:return
if peekb POSITION=13 then return
N=HEX_NUMBER(N):if ANY_ERRORS then return
SKIP
if (peekb POSITION=13) or (peekb POSITION<>':') then NEWO=N:return
POSITION++:NEWS=N
NEWO=HEX_NUMBER(NEWO)
}
proc DUMP_HEX(DS,DX)
{
ENDED=0 ;Say not at last range byte.
printh DS;":";DX;" ";
repeat 8 printhb DS[DX];DS[1+DX];" ";:DX+=2
DX-=16
print " ";
repeat 16
{
if DX=FINISH then ENDED=1
p=DS[DX]
if FILTER then
{
p=p and 127
if p<32 then p='.'
}
print chr p;:DX++
}
}
proc INSERT_CHAR(ASCII)
{
moveb 63-TX from COMMAND+TX to COMMAND+TX+1
pokeb COMMAND+TX,ASCII:TX++
}
proc REG_BAR(COL)
{
locate CUR_REG+1,70
SCR=CUR_REG*160+160+70*2+1
repeat 9 video[SCR]b=COL:SCR+=2
}
proc MAKE_SYMBOL(MA)
{
if (MA below ORG_IP) or (MA above FINISH) then return
if GET_SYMBOL then
{
if SYMBOLS then if search SYMBOLS from SYS|1 for MA then return
SYS[SYMBOLS*2+1]=MA:SYMBOLS++
}
}
proc PRINT_ADDRESS(PA_NUM)
{
MAKE_SYMBOL(PA_NUM)
if (MA below ORG_IP) or (MA above FINISH) then
{
if PA_NUM above 9fffh then print "0";
printh PA_NUM;"h";
}
else printh "L";PA_NUM;
}
proc PRINT_W(OO)
{
if OO and 1 then print "AX"; else print "AL";
}
proc PRINT_BYTE(PB_NUM)
{
if HEX then
{
if PB_NUM above 9fh then print "0";
printhb PB_NUM;"h";
}
else printb PB_NUM;
}
proc PRINT_WORD(PW_NUM)
{
if HEX then
{
PRINT_ADDRESS(PW_NUM)
}
else
{
MAKE_SYMBOL(PW_NUM)
if (MA below ORG_IP) or (MA above FINISH) then print PW_NUM;
else printh "L";PW_NUM;
}
}
proc PRINT_REG(A,R)
{
A+=(R and 7)*2
print chr peek A;chr peek (A+1);
}
proc PRINT_RW(RB)
{
if RB and 1
then PRINT_REG(REGW,RB)
else PRINT_REG(REGB,RB)
}
proc PRINT_MRM(MB,BW)
{
printh "[";
M_MOD=MB/64
M_RM=MB and 7
if (M_MOD=0) and (M_RM=6) then
{
PRINT_WORD(CS[IP]):IP+=2
goto EXIT_PRM
}
if M_MOD=3 then
{
REGT=REGB:if BW and 1 then REGT=REGW
locpos-=2
PRINT_REG(REGT,M_RM)
return
}
MSG=(searchb 100 from TABLE_RM for M_RM)+1
while peekb MSG<>255 print chr peek MSG;:MSG++
if M_MOD=2 then print "+";:PRINT_WORD(CS[IP]):IP+=2:goto EXIT_PRM
if M_MOD=1 then
{
DISP=CS[IP]b:IP++
if DISP<128
then print "+";:PRINT_BYTE(DISP)
else print "-";:PRINT_BYTE(256-DISP)
}
EXIT_PRM:
print "]";
}
function UNASSEMBLE_LINE(CS,IP)
{
BYTE=CS[IP]b
IADD=peek(LOOKUP_CODES+BYTE*2)
if (IADD>=FIRST_MESSAGE) and (IADD<=LAST_MESSAGE) then
{
PRINT_8088(IADD)
UNASM_CLINE
IP++
goto FINISH_UNASM
}
if not IADD then
{
goto NULL_NOT
NULL_CONTINUE:
pop DROP_ADDRESS
NULL_NOT:
PRINT_8088(I_DB)
PRINT_BYTE(BYTE):IP++
UNASM_CLINE
goto FINISH_UNASM
}
call IADD
FINISH_UNASM:
return IP
}
function UNASSEMBLE(CS,IP)
{
if not GET_SYMBOL then
{
START_IP=IP
printh CS":"IP;" ";
START_LOC=locpos
locpos+=15*2
if (SYMBOLS>0) and ((search SYMBOLS from SYS|1 for IP)<>0)
then printh "L";IP;" ";
else print " ";
}
IP=UNASSEMBLE_LINE(CS,IP)
if not GET_SYMBOL then
{
L1=locpos
locpos=START_LOC
LL=IP-START_IP
repeat LL printhb CS[START_IP];:START_IP++
if 6-LL then repeat 6-LL print " ";
if SCROLLF then print
else locpos=L1:UNASM_CLINE:locpos=4000-160:OUTPUT_LINE
}
else locpos=4000-160
return IP
}
proc BOXES
{
if BOXING and (video[0]b<>201) then
{
;Boxing required and not on screen yet.
colour 7
scroll 0,0,68,8,0
scroll 69,0,79,24,0
locate 0,0
print chr 201;
repeat 67 print chr 205;
print chr 187;
locate 8,0
print chr 200;
repeat 67 print chr 205;
print chr 188;
locate 1,0
repeat 7 print chr 186
for A=1 to 7:locate A,68:print chr 186;:next A
locate 0,69
print chr 201;
repeat 9 print chr 205;
print chr 187;
locate 14,69
print chr 200;
repeat 9 print chr 205;
print chr 188;
for A=1 to 13
locate A,69:print chr 186;:locate A,79:print chr 186;
next A
colour 14
locate 15,69
print chr 201;
repeat 9 print chr 205;
print chr 187;
locate 24,69
print chr 200;
repeat 9 print chr 205;
print chr 188;
for A=16 to 23
locate A,69:print chr 186;:locate A,79:print chr 186;
next A
colour 15
restore REG_DISPLAY
for Y=1 to 13
readb A,B
locate Y,71:printh chr A;chr B;"=";
next Y
locate 16,70:print "F1 Status";
locate 17,70:print "F2 Unasm";
locate 18,70:print "F4 Dump";
locate 23,70:print "F10 Trace";
}
if BOXING then
{
colour 15
REGP=REGISTERS
BOX_START=peek REG_IP
push SCROLLF
SYMBOLS=0:GET_SYMBOL=0:SCROLLF=1
for Y=1 to 13
locate Y,74:printh peek REGP:REGP+=2
if Y<8 then
{
locate Y,2
UNASM_CLINE
locate Y,2
BOX_START=UNASSEMBLE(peek (REGSEGS+2),BOX_START)
}
next Y
pop SCROLLF
}
}
proc RESET_REGS
{
poke REGSEGS,PRG
poke REGSEGS+2,PRG
poke REGSEGS+4,PRG
poke REGSEGS+6,PRG
poke REG_IP,100H
fill 8 from REGISTERS with 0
poke REGISTERS+8,-1 ;Stack.
CUR_IP=100h
CUR_DX=100h
DISK_OUTPUT=0
PRINTER_OUTPUT=0
SCROLLF=1
GET_SYMBOL=0
}
proc LOAD_FILE(FIRST) ;Calls RESET_REGS from here.
{
if FIRST then
{
N=82h
pokeb searchb 127 from 81h for 13,0 ;Make ASCIIZ
if peekb 81h=0 then FIRST=0
}
if not FIRST then
{
print "Program name (.COM) ";
loctocur
fill 32 from FILENAME+2 with 0
inputs FILENAME
if peekb (FILENAME+2)=0 then goto NO_LOAD
F=searchb peekb (FILENAME+1) from FILENAME+2 for '.'
if not F then
{
F=searchb 64 from FILENAME+2 for 0
pokeb F,'.'
pokeb F+1,'C'
pokeb F+2,'O'
pokeb F+3,'M'
pokeb F+4,0
}
N=FILENAME+2
print
}
load N,PRG|100h
if error then
{
print "Program not found."
goto START
}
LEN=(searchb 64 from N for 0)-N
locate 0,34-(LEN/2)
print " ";
while peekb N print chr ucase peek N;:N++
print " ";
NO_LOAD:
RESET_REGS
}
proc END_IT_ALL
{
reg dx=BRK_OFF,ds=BRK_SEG:dos 25(3)
reg ds=reg cs
reg dx=INT_OFF,ds=INT_SEG:dos 25(1)
reg ds=reg cs
reg dx=SCR_OFF,ds=SCR_SEG:dos 25(10)
reg ds=reg cs
cursor 24,0
if DISK_OUTPUT then CLOSE5:if error then print "Error closing disk file!":beep
terminate
}
START:
BOXES
locate 13,0
LOAD_FILE(1) ;Load from command line or get from input.
MAIN:
TYPED=0:TX=0:INSERT=0
fill 32 from COMMAND with 2020h
MAIN2:
CUR_CS=peek (REGSEGS+2)
CUR_DS=peek (REGSEGS+6)
BOXES
locate 24,0
print ">";
forever
{
if BOXING then REG_BAR(112)
locate 24,1
colour 7
PRT=64
if TYPED then
{
for A=1 to TYPED:print chr(peek (COMMAND-1+A));:PRT--
next A
}
cursor 24,tx+1
if PRT then repeat PRT print chr' ';
if MONO then
{
if INSERT then cursor size 7,12 else cursor size 11,12
}
else
{
if INSERT then cursor size 4,7 else cursor size 6,7
}
wait for keypressed
KS=keyscan
SS=high KS
KK=low KS
if BOXING then
{
REG_BAR(15)
if KS=20480 then CUR_REG++
if KS=18432 then CUR_REG--
if CUR_REG<0 then CUR_REG=12
if CUR_REG>12 then CUR_REG=0
if KS=20011 then
{
CH=0:PV=0
locate CUR_REG+1,74:print " ";:locpos-=8
GET_PLUS:
loctocur
cursor high curpos,low curpos+CH
wait for keypressed
KS=keyscan:K=ucase low KS
if K=27 then goto MAIN
if K=13 then
{
if CH then poke REGISTERS+CUR_REG*2,PV
goto MAIN
}
if KS=3592 then CH=0:print " ";:locpos-=8
PRT=K
K-='0'
if K>9 then K-=7
if (CH<4) and (K>=0) and (K<16) then
{
print bios chr PRT;:CH++
PV=PV*16+K
}
goto GET_PLUS
}
REG_BAR(112)
}
if ((KS=16384) or (KS=29952)) and (TX<TYPED) then TYPED=TX
if KS=18176 then TX=0
if KS=20224 then TX=TYPED
if (KS=19200) and (TX>0) then TX--
if (KS=19712) and (TX<62) then TX++
if KS=21248
then {
if TX<TYPED then TYPED--
moveb 64-TX from COMMAND+TX+1 to COMMAND+TX
}
if KS=15616 then move 32 from PREVIOUS to COMMAND:TYPED=LAST_TYPED:TX=TYPED
;Functions.
locate 24,0
if KS=15104 then print:gosub STATUS:goto MAIN2
if KS=15360 then WAITFKEY=0:print:FINISH=CUR_IP+UNASM_SCREEN:gosub UNASM_FUNC:goto MAIN2
if KS=15872 then WAITFKEY=0:print:FINISH=CUR_DX+127:gosub DUMP_FUNC:goto MAIN2
if KS=20992 then INSERT=not INSERT
if (KK=13) and (TYPED>0) then pokeb COMMAND+TYPED,13:goto ENDCOMMAND
if KK=27 then TYPED=0:TX=0
if KS=3592 then
{
moveb 63-TX from COMMAND+TX to COMMAND-1+TX
if (TX<=TYPED) and (TX>0) then TYPED--
if TX then tx--
}
if KK>31 then
{
if TYPED>=62 then beep
else
{
if INSERT=0 then
{
pokeb COMMAND+TX,KK
TX++
if TX>TYPED then TYPED=TX
}
else
{
INSERT_CHAR(KK)
TYPED++
}
}
}
}
ENDCOMMAND:
move 32 from COMMAND to PREVIOUS
LAST_TYPED=TYPED
ANY_ERRORS=0
cursor 32,0
locate 24,0
for X=COMMAND to COMMAND+63:pokeb X,ucase peekb X:next X
WAITING=0 ;Say not line skip.
print
C1=peekb COMMAND
C2=peekb (COMMAND+1)
C3=peekb (COMMAND+2)
C4=peekb (COMMAND+3)
if C1='?' then
{
LINES=1
ADDRESS=HELP_TEXT
while peekb ADDRESS
{
if peekb ADDRESS=13 then
{
if BOXING and (LINES=16) then
{
wait for keypressed
LINES=0
K=key:if K=27 then print:goto GNULL
}
LINES++
print
}
else print chr peek ADDRESS;
ADDRESS++
}
goto GNULL
}
F=searchb 15 from KEY_TABLE for C1
WAITFKEY=1
POSITION=COMMAND+1 ;Current scan position, used for evaluation.
if F then
{
F-=KEY_TABLE
call peek (KEY_ADDR+F*2)
}
else
{
WHAT_KEY:
print "What?"
}
GNULL:
goto MAIN
SCRCHK:
pushall
push reg ax
reg ds=reg cs
pop AX
RT=reg cx:RB=reg dx
if AX=0601h then OUTPUT_LINE
if BOXING and (AX=0601h) and (RT=0) and (RB=184fh) then
{
popall
push reg ax
reg cx=0900h
reg dx=1844h
inline 58h
pushall
}
popall
inline 0eah
SOFF:
data 0
SSEG:
data 0
FILENAME:
string 64
REG_DISPLAY:
datab 'AX','CX','DX','BX','SP','BP','SI','DI','ES','CS','SS','DS','IP'
REGISTERS:
data 0,0,0,0
data 65535,0,0,0
REGSEGS:
data 0,0,0,0
REG_IP:
data 100h
OUTPUT_FILE:
string 40
DEFAULT_DISK:
fname 'DC.LST'
REGW:
datab 'AXCXDXBXSPBPSIDI'
REGB:
datab 'ALCLDLBLAHCHDHBH'
SEG:
datab 'ESCSSSDS'
GROUP1:
data I_TEST
data I_NULL
data I_NOT
data I_NEG
data I_MUL
data I_IMUL
data I_DIV
data I_IDIV
GROUP2:
data I_INC
data I_DEC
data I_CALL
data I_CALLF
data I_JUMP
data I_JMPF
data I_PUSH
data I_NULL
SHIFT:
data I_ROL
data I_ROR
data I_RCL
data I_RCR
data I_SHL
data I_SHR
data I_NULL
data I_SAR
IMMED:
data I_ADD
data I_OR
data I_ADC
data I_SBB
data I_AND
data I_SUB
data I_XOR
data I_CMP
TABLE_RM:
datab 0,'BX+SI',255
datab 1,'BX+DI',255
datab 2,'BP+SI',255
datab 3,'BP+DI',255
datab 4,'SI',255
datab 5,'DI',255
datab 6,'BP',255
datab 7,'BX',255
KEY_TABLE:
datab 'UGDRIOQTECSFMPV'
KEY_ADDR:
data KEY_UNASM,GNULL,KEY_DUMP,GNULL
data KEY_INPUT,KEY_OUTPUT,KEY_QUIT,GNULL
data KEY_ENTER,KEY_COMP,KEY_SEARCH,GNULL
data KEY_MOVE,GNULL,KEY_VERSION
HELP_TEXT:
datab 13
datab 'DC (DEBUG CONTROL) WRITTEN BY PETER CAMPBELL',13
datab 13
datab 'C - source count destination (compare blocks of memory)',13
datab 'CLS - (clear screen, full screen mode)',13
datab 'D - start finish (dump memory in hex and ascii)',13
datab 'DRAW - (draw box, half screen mode)',13
datab 'E - start (enter bytes from address)',13
datab 'F - start repeat string/bytes (fill memory)',13
datab 'G - breakpoint,=address (go to address)',13
datab 'I - port (input byte from port)',13
datab 'IO - (update current I/O settings)',13
datab 'M - source count destination (move memory)',13
datab 'O - port byte (output byte to port)',13
datab 'P - (proceed, execute one instruction)',13
datab 'Q - (quit DC)',13
datab 'R - register (set/display register contents)',13
datab 'S - start count string/bytes (search for bytes)',13
datab 'T - count (trace instructions)',13
datab 'U - start finish (unassemble)',13
datab 'V - (version?)',13
datab 0
KEY_QUIT:
END_IT_ALL
KEY_DUMP:
if (C2='R') and (C3='A') and (C4='W') then
{
BOXING=1
locate 0,0:print " ";
return
}
NEW_SEG(CUR_DS,CUR_DX):if ANY_ERRORS then return
CUR_DS=NEWS:CUR_DX=NEWO and 65520
SKIP
FINISH=HEX_NUMBER(65535):if ANY_ERRORS then return
DUMP_FUNC:
NSCR=0:OLD_NSCR=0
forever
{
if not NSCR then
{
if OLD_NSCR then print
DUMP_HEX(CUR_DS,CUR_DX)
OLD_NSCR=0
CUR_DX+=16
print
if ENDED then return
}
NSCR=0
if WAIT_KEY then return
if KS=18432 then CUR_DX-=272
if KS=20480 then CUR_DX-=240
if KS=18688 then CUR_DX-=512
if (KS=18432) or (KS=20480) or (KS=20736) or (KS=18688) then
{
NSCR=1
locate 9,0
for L=1 to 16
DUMP_HEX(CUR_DS,CUR_DX):CUR_DX+=16
if L<>16 then print
next L
OLD_NSCR=1
}
}
KEY_COMP:
if (C2='L') and (C3='S') then cls:BOXING=0:return
if END_LINE then print "Compare what?":return
NEW_SEG(CUR_DS,0):if ANY_ERRORS then return
CDS=NEWS:CDX=NEWO
if END_LINE then print "How many?":return
COUNT=HEX_NUMBER(0):if ANY_ERRORS then return
if END_LINE then print "With what?":return
NEW_SEG(CUR_DS,0):if ANY_ERRORS then return
CES=NEWS:CEX=NEWO
DIFFERENCES=0
while COUNT
{
F=compareb COUNT at CDS|CDX with CES|CEX
if (F<>0) or ((CDX=0) and (CDS[CDX]b<>CES[CEX]b)) then
{
COUNT-=F-CDX+1
CEX+=F-CDX:CDX=F
printh CDS":"CDX" ";
printhb CDS[CDX]" ";
printh CES":"CEX" ";
printhb CES[CEX]
DIFFERENCES++:CDX++:CEX++
if WAIT_KEY then return
}
else goto PRINT_DIFF
}
PRINT_DIFF:
print DIFFERENCES" differences."
return
KEY_INPUT:
if C2='O' then goto KEY_IO
SKIP
PORT=HEX_NUMBER(65535):if ANY_ERRORS then return
if PORT=65535 then print "Port?":return
I=in PORT
printhb I;"H (";
printb I;")"
return
KEY_IO:
IO_OUT=0
print
print "Current output -"
colour 15
if DISK_OUTPUT then
{
print " Disk file: ";
M=OUTPUT_FILE+2
while peekb M print chr lcase peek M;:M++
print
}
if PRINTER_OUTPUT then print " Printer."
if SCROLLF then print " Screen."
colour 7
print cr "Press D to turn disk output ";
PRINT_OO(not DISK_OUTPUT):print ","
print " P to turn printer output ";
PRINT_OO(not PRINTER_OUTPUT):print ","
print " S to turn screen output ";
PRINT_OO(not SCROLLF):print ".";:loctocur
wait for keypressed
print cr
K=ucase key
if K='D' then
{
DISK_OUTPUT=not DISK_OUTPUT
if DISK_OUTPUT then
{
loctocur
print bios "Disk file name: [DC.LST] ";
inputs OUTPUT_FILE
print
if not peekb (OUTPUT_FILE+2)
then moveb 7 from DEFAULT_DISK to OUTPUT_FILE+2
create #5,OUTPUT_FILE+2
if error then print "Can't open file!":beep:DISK_OUTPUT=0
DPLACE=DISK_START
}
else CLOSE5:if error then print "Error closing disk file!":beep
goto KEY_IO
}
if K='P' then
{
PRINTER_OUTPUT=not PRINTER_OUTPUT
goto KEY_IO
}
if K='S' then
{
SCROLLF=not SCROLLF
goto KEY_IO
}
IO_OUT=1
return
KEY_OUTPUT:
SKIP
PORT=HEX_NUMBER(65535):if ANY_ERRORS then return
if PORT=65535 then print "Port?":return
SKIP
O=HEX_NUMBER(1000):if ANY_ERRORS then return
if O=1000 then print "Out what?":return
out PORT,O
print "Done."
return
KEY_ENTER:
NEW_SEG(CUR_DS,CUR_DX):if ANY_ERRORS then return
forever
{
printh NEWS;":";NEWO;" ";
printhb NEWS[NEWO];" - ";
PV=0:CH=0:OLDO=NEWO
GET_ENTER:
loctocur
cursor high curpos,low curpos+CH
wait for keypressed
KS=keyscan:K=ucase low KS
if K=27 then print:return
if KS=18432 then NEWO--
if KS=20480 then NEWO++
if K=13 then
{
if CH then NEWS[NEWO]b=PV
NEWO++
}
if KS=3592 then CH=0:print " ";:locpos-=4
PRT=K
K-='0'
if K>9 then K-=7
if (CH<2) and (K>=0) and (K<16) then
{
print bios chr PRT;:CH++
PV=PV*16+K
}
if NEWO=OLDO then goto GET_ENTER
print
}
KEY_MOVE:
if END_LINE then print "Move what?":return
NEW_SEG(CUR_DS,0):if ANY_ERRORS then return
CDS=NEWS:CDX=NEWO
if END_LINE then print "How many?":return
COUNT=HEX_NUMBER(0):if ANY_ERRORS then return
if END_LINE then print "Move where?":return
NEW_SEG(CUR_DS,0):if ANY_ERRORS then return
CES=NEWS:CEX=NEWO
moveb COUNT from CDS|CDX to CES|CEX
print "Moved."
return
KEY_UNASM:
NEW_SEG(CUR_CS,CUR_IP):if ANY_ERRORS then return
CUR_CS=NEWS:CUR_IP=NEWO
SKIP
FINISH=HEX_NUMBER(CUR_IP+UNASM_SCREEN):if ANY_ERRORS then return
UNASM_FUNC:
SYMBOLS=0:OSF=SCROLLF:SCROLLF=0
GET_SYMBOL=1
ORG_IP=CUR_IP
while (CUR_IP below FINISH) and (SYMBOLS<MAX_SYMBOLS)
{
locate 24,0:printh chr '-';FINISH-CUR_IP;" ";
CUR_IP=UNASSEMBLE(CUR_CS,CUR_IP)
}
locate 24,0:UNASM_CLINE:locate 24,0
GET_SYMBOL=0
SCROLLF=OSF
CUR_IP=ORG_IP
while CUR_IP below FINISH
{
CUR_IP=UNASSEMBLE(CUR_CS,CUR_IP)
if WAIT_KEY then return
}
return
STATUS:
print "DC Options -"
print "Unassemble in hex? [";chr 'N'+11*HEX;"] ";
HEX=YESNO(HEX)
print "Scroll delay? (0-5) [";chr DELAY+'0'"] ";
loctocur
GET_DELAY:
wait for keypressed
K=key:if K=13 then print:goto NEXT_STAT
if (K<'0') or (K>'5') then goto GET_DELAY
DELAY=K-'0'
print chr K
NEXT_STAT:
print "Filter ascii dump? ["chr FILTER*11+'N'"] ";
FILTER=YESNO(FILTER)
return
KEY_SEARCH:
return
KEY_VERSION:
print cr"DC (DEBUG CONTROL) WRITTEN BY PETER CAMPBELL"
print "Version 1.55 (19/7/88)"cr
return
;Disassembly tables.
FIRST_MESSAGE:
I_XLAT:
fname 'XLAT'
I_RET:
fname 'RET'
I_LAHF:
fname 'LAHF'
I_SAHF:
fname 'SAHF'
I_POPF:
fname 'POPF'
I_PUSHF:
fname 'PUSHF'
I_AAA:
fname 'AAA'
I_DAA:
fname 'DAA'
I_AAS:
fname 'AAS'
I_DAS:
fname 'DAS'
I_CBW:
fname 'CBW'
I_CWD:
fname 'CWD'
I_MOVSB:
fname 'MOVSB'
I_MOVSW:
fname 'MOVSW'
I_STOSB:
fname 'STOSB'
I_STOSW:
fname 'STOSW'
I_LODSB:
fname 'LODSB'
I_LODSW:
fname 'LODSW'
I_SCASB:
fname 'SCASB'
I_SCASW:
fname 'SCASW'
I_CMPSB:
fname 'CMPSB'
I_CMPSW:
fname 'CMPSW'
I_REPNZ:
fname 'REPNZ'
I_REPZ:
fname 'REPZ'
I_RETF:
fname 'RETF'
I_INT3:
fname 'INT 3'
I_INTO:
fname 'INTO'
I_IRET:
fname 'IRET'
I_CLC:
fname 'CLC'
I_STC:
fname 'STC'
I_CMC:
fname 'CMC'
I_NOP:
fname 'NOP'
I_CLD:
fname 'CLD'
I_STD:
fname 'STD'
I_CLI:
fname 'CLI'
I_STI:
fname 'STI'
I_HLT:
fname 'HLT'
I_WAIT:
fname 'WAIT'
I_LOCK:
fname 'LOCK'
I_INT:
fname 'INT'
I_CALL:
fname 'CALL'
I_JUMP:
fname 'JMP'
I_DB:
fname 'DB'
I_JE:
fname 'JE'
I_JL:
fname 'JL'
I_JLE:
fname 'JLE'
I_JB:
fname 'JB'
I_JBE:
fname 'JBE'
I_JP:
fname 'JP'
I_JO:
fname 'JO'
I_JS:
fname 'JS'
I_JNE:
fname 'JNE'
I_JNL:
fname 'JNL'
I_JG:
fname 'JG'
I_JAE:
fname 'JAE'
I_JA:
fname 'JA'
I_JPO:
fname 'JPO'
I_JNO:
fname 'JNO'
I_JNS:
fname 'JNS'
I_LOOP:
fname 'LOOP'
I_LOOPZ:
fname 'LOOPZ'
I_LOOPNZ:
fname 'LOOPNZ'
I_JCXZ:
fname 'JCXZ'
I_PUSH:
fname 'PUSH'
I_POP:
fname 'POP'
I_XCHG:
fname 'XCHG'
I_INC:
fname 'INC'
I_DEC:
fname 'DEC'
I_IN:
fname 'IN'
I_OUT:
fname 'OUT'
I_ADC:
fname 'ADC'
I_ADD:
fname 'ADD'
I_SUB:
fname 'SUB'
I_SBB:
fname 'SBB'
I_CMP:
fname 'CMP'
I_AND:
fname 'AND'
I_TEST:
fname 'TEST'
I_OR:
fname 'OR'
I_XOR:
fname 'XOR'
I_MOV:
fname 'MOV'
I_JMPF:
fname 'JMPF'
I_CALLF:
fname 'CALLF'
I_JMPS:
fname 'JMPS'
I_LEA:
fname 'LEA'
I_LDS:
fname 'LDS'
I_LES:
fname 'LES'
I_NOT:
fname 'NOT'
I_NEG:
fname 'NEG'
I_MUL:
fname 'MUL'
I_IMUL:
fname 'IMUL'
I_DIV:
fname 'DIV'
I_IDIV:
fname 'IDIV'
I_ROL:
fname 'ROL'
I_ROR:
fname 'ROR'
I_RCL:
fname 'RCL'
I_RCR:
fname 'RCR'
I_SHL:
fname 'SHL'
I_SHR:
fname 'SHR'
I_SAR:
fname 'SAR'
I_AAD:
fname 'AAD'
I_AAM:
fname 'AAM'
I_NULL:
fname '*What?*'
I_SPACE:
fname ''
LAST_MESSAGE:
LOOKUP_CODES:
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;0
data R_ADD,R_ADD,R_PUSHS,R_POPS ;4
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;8
data R_OR,R_OR,R_PUSHS,0 ;12
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;16
data R_ADC,R_ADC,R_PUSHS,R_POPS ;20
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;24
data R_SBB,R_SBB,R_PUSHS,R_POPS ;28
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;32
data R_AND,R_AND,R_OVERS,I_DAA ;36
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;40
data R_SUB,R_SUB,R_OVERS,I_DAS ;44
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;48
data R_XOR,R_XOR,R_OVERS,I_AAA ;52
data R_IMMED,R_IMMED,R_IMMED,R_IMMED ;56
data R_CMP,R_CMP,R_OVERS,I_AAS ;60
data R_INC,R_INC,R_INC,R_INC ;64
data R_INC,R_INC,R_INC,R_INC ;68
data R_DEC,R_DEC,R_DEC,R_DEC ;72
data R_DEC,R_DEC,R_DEC,R_DEC ;76
data R_PUSH,R_PUSH,R_PUSH,R_PUSH ;80
data R_PUSH,R_PUSH,R_PUSH,R_PUSH ;84
data R_POP,R_POP,R_POP,R_POP ;88
data R_POP,R_POP,R_POP,R_POP ;92
data 0,0,0,0 ;96
data 0,0,0,0 ;100
data 0,0,0,0 ;104
data 0,0,0,0 ;108
data R_JO,R_JNO,R_JB,R_JAE ;112
data R_JE,R_JNE,R_JBE,R_JA ;116
data R_JS,R_JNS,R_JP,R_JPO ;120
data R_JL,R_JNL,R_JLE,R_JG ;124
data R_IMMEDI,R_IMMEDI,R_IMMEDI,R_IMMEDI ;128
data R_TESTW,R_TESTW,R_XCHGW,R_XCHGW ;132
data R_MOVR,R_MOVR,R_MOVR,R_MOVR ;136
data R_MOVST,R_LEA,R_MOVTS,R_POPRM ;140
data I_NOP,R_XCHG,R_XCHG,R_XCHG ;144
data R_XCHG,R_XCHG,R_XCHG,R_XCHG ;148
data I_CBW,I_CWD,R_CALLF,I_WAIT ;152
data I_PUSHF,I_POPF,I_SAHF,I_LAHF ;156
data R_MOVMA,R_MOVMA,R_MOVAM,R_MOVAM ;160
data I_MOVSB,I_MOVSW,I_CMPSB,I_CMPSW ;164
data R_TEST,R_TEST,I_STOSB,I_STOSW ;168
data I_LODSB,I_LODSW,I_SCASB,I_SCASW ;172
data R_MOVIR,R_MOVIR,R_MOVIR,R_MOVIR ;176
data R_MOVIR,R_MOVIR,R_MOVIR,R_MOVIR ;180
data R_MOVIR,R_MOVIR,R_MOVIR,R_MOVIR ;184
data R_MOVIR,R_MOVIR,R_MOVIR,R_MOVIR ;188
data 0,0,R_RETSP,I_RET ;192
data R_LES,R_LDS,R_MOVIRM,R_MOVIRM ;196
data 0,0,R_RETFSP,I_RETF ;200
data I_INTO,R_INT,I_INTO,I_IRET ;204
data R_SHIFT,R_SHIFT,R_SHIFT,R_SHIFT ;208
data R_AAM,R_AAD,0,I_XLAT ;212
data 0,0,0,0 ;216
data 0,0,0,0 ;220
data R_LOOPNZ,R_LOOPZ,R_LOOP,R_JCXZ ;224
data R_INP,R_INP,R_OUTP,R_OUTP ;228
data R_CALL,R_JUMP,R_JMPF,R_JMPS ;232
data R_INDX,R_INDX,R_OUTDX,R_OUTDX ;236
data I_LOCK,0,I_REPNZ,I_REPZ ;240
data I_HLT,I_CMC,R_MATH,R_MATH ;244
data I_CLC,I_STC,I_CLI,I_STI ;248
data I_CLD,I_STD,R_GROUP2,R_GROUP2 ;252
R_INT:
PRINT_8088(I_INT)
R_BYTE:
PRINT_BYTE(CS[IP+1])
IP+=2
return
R_RETSP:
PRINT_8088(I_RET)
R_WORD:
PRINT_WORD(CS[IP+1])
IP+=3
return
R_RETFSP:
PRINT_8088(I_RETF)
goto R_WORD
R_CALL:
PRINT_8088(I_CALL)
R_NEAR:
IA=CS[IP+1]:IP+=3
if IA>=0 then IA+=IP else IA=IP-(0-IA)
PRINT_ADDRESS(IA)
return
R_JUMP:
PRINT_8088(I_JUMP)
goto R_NEAR
R_JE:
PRINT_8088(I_JE)
PRINT_OFFSET:
OFS=CS[IP+1]b
IP+=2
if OFS<128
then PRINT_ADDRESS(IP+OFS)
else PRINT_ADDRESS(IP-(256-OFS))
return
R_JL:
PRINT_8088(I_JL)
goto PRINT_OFFSET
R_JLE:
PRINT_8088(I_JLE)
goto PRINT_OFFSET
R_JB:
PRINT_8088(I_JB)
goto PRINT_OFFSET
R_JBE:
PRINT_8088(I_JBE)
goto PRINT_OFFSET
R_JP:
PRINT_8088(I_JP)
goto PRINT_OFFSET
R_JO:
PRINT_8088(I_JO)
goto PRINT_OFFSET
R_JS:
PRINT_8088(I_JS)
goto PRINT_OFFSET
R_JNE:
PRINT_8088(I_JNE)
goto PRINT_OFFSET
R_JNL:
PRINT_8088(I_JNL)
goto PRINT_OFFSET
R_JG:
PRINT_8088(I_JG)
goto PRINT_OFFSET
R_JAE:
PRINT_8088(I_JAE)
goto PRINT_OFFSET
R_JA:
PRINT_8088(I_JA)
goto PRINT_OFFSET
R_JPO:
PRINT_8088(I_JPO)
goto PRINT_OFFSET
R_JMPS:
PRINT_8088(I_JMPS)
goto PRINT_OFFSET
R_JNO:
PRINT_8088(I_JNO)
goto PRINT_OFFSET
R_JNS:
PRINT_8088(I_JNS)
goto PRINT_OFFSET
R_LOOP:
PRINT_8088(I_LOOP)
goto PRINT_OFFSET
R_LOOPZ:
PRINT_8088(I_LOOPZ)
goto PRINT_OFFSET
R_LOOPNZ:
PRINT_8088(I_LOOPNZ)
goto PRINT_OFFSET
R_JCXZ:
PRINT_8088(I_JCXZ)
goto PRINT_OFFSET
R_PUSH:
PRINT_8088(I_PUSH)
PRINT_LOW_REGW:
PRINT_REG(REGW,BYTE)
IP++
return
R_POP:
PRINT_8088(I_POP)
goto PRINT_LOW_REGW
R_XCHG:
PRINT_8088(I_XCHG)
print "AX,";
goto PRINT_LOW_REGW
R_INC:
PRINT_8088(I_INC)
goto PRINT_LOW_REGW
R_DEC:
PRINT_8088(I_DEC)
goto PRINT_LOW_REGW
R_POPS:
PRINT_8088(I_POP)
PRINT_MID_SEG:
PRINT_REG(SEG,BYTE/8)
IP++
return
R_PUSHS:
PRINT_8088(I_PUSH)
goto PRINT_MID_SEG
R_INP:
PRINT_8088(I_IN)
PRINT_W(BYTE)
print ",";
goto R_BYTE
R_OUTP:
PRINT_8088(I_OUT)
gosub R_BYTE
print ",";
PRINT_W(BYTE)
return
R_INDX:
PRINT_8088(I_IN)
PRINT_W(BYTE)
print ",DX";
IP++
return
R_OUTDX:
PRINT_8088(I_OUT)
print "DX,";
PRINT_W(BYTE)
IP++
return
R_ADC:
PRINT_8088(I_ADC)
R_WDW1:
PRINT_W(BYTE)
print ",";
WDW1:
if BYTE and 1
then PRINT_WORD(CS[IP+1]):IP+=3
else PRINT_BYTE(CS[IP+1]):IP+=2
return
R_ADD:
PRINT_8088(I_ADD)
goto R_WDW1
R_SUB:
PRINT_8088(I_SUB)
goto R_WDW1
R_SBB:
PRINT_8088(I_SBB)
goto R_WDW1
R_CMP:
PRINT_8088(I_CMP)
goto R_WDW1
R_AND:
PRINT_8088(I_AND)
goto R_WDW1
R_TEST:
PRINT_8088(I_TEST)
goto R_WDW1
R_OR:
PRINT_8088(I_OR)
goto R_WDW1
R_XOR:
PRINT_8088(I_XOR)
goto R_WDW1
R_MOVMA:
PRINT_8088(I_MOV)
PRINT_W(BYTE)
print ",[";
PRINT_WORD(CS[IP+1])
print "]";
IP+=3
return
R_MOVAM:
PRINT_8088(I_MOV)
print "[";
PRINT_WORD(CS[IP+1])
print "],";
PRINT_W(BYTE)
IP+=3
return
R_CALLF:
PRINT_8088(I_CALLF)
PRINT_ABS:
printh CS[IP+1];"h:";CS[IP+3];"h";
IP+=5
return
R_JMPF:
PRINT_8088(I_JMPF)
goto PRINT_ABS
R_LEA:
PRINT_8088(I_LEA)
R_MRD:
BYTE=CS[IP+1]b
PRINT_REG(REGW,BYTE/8)
R_MRM:
BYTE=CS[IP+1]b
print ",";
MRM2:
IP+=2
PRINT_MRM(BYTE,1)
return
R_LDS:
PRINT_8088(I_LDS)
goto R_MRD
R_LES:
PRINT_8088(I_LES)
goto R_MRD
R_XCHGW:
PRINT_8088(I_XCHG)
REGT=REGB:if BYTE and 1 then REGT=REGW
BYTE=CS[IP+1]b
PRINT_REG(REGT,BYTE/8)
goto R_MRM
R_MATH:
SECI=CS[IP+1]b
SECM=peek(GROUP1+((SECI/8) and 7)*2)
if SECM=I_NULL then goto NULL_CONTINUE
PRINT_8088W(SECM)
IP+=2
PRINT_MRM(SECI,BYTE)
if SECM=I_TEST then
{
print ",";
PRINT_WORD(CS[IP])
IP+=2
}
return
R_SHIFT:
SECI=CS[IP+1]b
SECM=peek(SHIFT+((SECI/8) and 7)*2)
if SECM=I_NULL then goto NULL_CONTINUE
PRINT_8088W(SECM)
IP+=2
PRINT_MRM(SECI,BYTE)
if BYTE and 2 then print ",CL"; else print ",1";
return
R_GROUP2:
SECI=CS[IP+1]b
SECM=peek(GROUP2+((SECI/8) and 7)*2)
if SECM=I_NULL then goto NULL_CONTINUE
if (SECM=I_DEC) or (SECM=I_INC)
then PRINT_8088W(SECM)
else PRINT_8088(SECM)
IP+=2
PRINT_MRM(SECI,BYTE)
return
R_IMMED:
PRINT_8088W(peek(IMMED+2*((BYTE/8) and 7)))
MOVR2:
REGT=REGB:if BYTE and 1 then REGT=REGW
REGS=CS[IP+1]b
IP+=2
if BYTE and 2 then
{
PRINT_REG(REGT,REGS/8)
print ",";
PRINT_MRM(REGS,BYTE)
}
else
{
PRINT_MRM(REGS,BYTE)
print ",";
PRINT_REG(REGT,REGS/8)
}
return
R_POPRM:
BYTE=CS[IP+1]b
if BYTE and 111000b then goto NULL_CONTINUE
PRINT_8088(I_POP)
goto MRM2
R_IMMEDI:
REGS=CS[IP+1]b
PRINT_8088W(peek(IMMED+2*((REGS/8) and 7)))
IP+=2
PRINT_MRM(REGS,BYTE)
print ",";
SW=BYTE and 3
IA=CS[IP]b:IP++
if SW=1 then IA=CS[IP-1]:IP++
if SW=3 then if IA>127 then IA=0-(256-IA)
PRINT_WORD(IA)
return
R_AAM:
PRINT_8088(I_AAM)
PBAA:
PRINT_BYTE(CS[IP+1]b)
IP+=2
return
R_AAD:
PRINT_8088(I_AAD)
goto PBAA
R_TESTW:
PRINT_8088W(I_TEST)
REGT=REGB:if BYTE and 1 then REGT=REGW
REGS=CS[IP+1]b
IP+=2
PRINT_REG(REGT,REGS/8)
print ",";
PRINT_MRM(REGS,BYTE)
return
R_MOVR:
PRINT_8088W(I_MOV)
goto MOVR2
R_MOVST:
PRINT_8088(I_MOV)
BYTE=CS[IP+1]b
gosub MRM2
print ",";
PRINT_REG(SEG,(BYTE/8) and 3)
return
R_MOVTS:
PRINT_8088(I_MOV)
BYTE=CS[IP+1]b
PRINT_REG(SEG,(BYTE/8) and 3)
print ",";
goto MRM2
R_MOVIRM:
REGS=CS[IP+1]b
if REGS and 111000b then goto NULL_CONTINUE
PRINT_8088W(I_MOV)
IP+=2
PRINT_MRM(REGS,BYTE)
print ",";
if BYTE and 1
then PRINT_WORD(CS[IP]):IP+=2
else PRINT_BYTE(CS[IP]b):IP++
return
R_MOVIR:
PRINT_8088(I_MOV)
IP++
REGT=REGB:if BYTE and 8 then REGT=REGW
PRINT_REG(REGT,BYTE)
print ",";
if BYTE and 8
then PRINT_WORD(CS[IP]):IP+=2
else PRINT_BYTE(CS[IP]b):IP++
return
R_OVERS:
PRINT_8088(I_SPACE)
IP++
PRINT_REG(SEG,(BYTE/8) and 3)
print ":";
return